/// @brief   tcp客户端代码  
///  
/// 实现tcp客户端的相关接口  

#include <iostream>
using namespace std;

#ifdef __cplusplus
extern "C" {               // 告诉编译器下列代码要以C链接约定的模式进行链接
#endif

#include <stdio.h>  
#include <sys/types.h>  
#include <sys/socket.h>  
#include <netinet/in.h>  
#include <unistd.h>  
#include <errno.h>  
#include <string.h>  

#include "client.h" 

#ifdef __cplusplus
}
#endif


 
int g_hSocket;  // socket handle 
int connect_server(char *destIp, int destPort){
    struct sockaddr_in in_address;
    g_hSocket = socket(AF_INET, SOCK_STREAM, 0);

    //set server addr
    in_address.sin_family = AF_INET;
    in_address.sin_addr.s_addr = inet_addr(destIp);
    in_address.sin_port        = htons(destPort);

    int result = connect(g_hSocket, (struct sockaddr*)&in_address, sizeof(in_address));
    if(-1 == result){
        cout<<"[tcp client] can't connect server !"<<endl;
        return -1;
    }
    return 0;
}

int close_connect(){
    cout<<"close connect with server !"<<endl;
    close(g_hSocket);
    return 0;
}

int send_cmd(serverPack sPack){
    int recvBytes = 0;
    int sendBytes = 0;
    returnPack rPack;

    //cmd_header
    memcpy(sPack.cmdHeader, tcp_cmd_header, tcp_cmd_header_len);

    //send cmd
    while(1){
        sendBytes = send(g_hSocket, (uint8_t*)&sPack, server_pack_len, 0);
        if(sendBytes == server_pack_len){
            cout<<"successfully send "<< server_pack_len <<" bytes"<<endl;
            break;
        }else if(sendBytes <= 0 && errno != EINTR && errno != EWOULDBLOCK && errno != EAGAIN){
            cout<<"disconnected or other errors!"<<endl;
            return -1;
        }else{
            continue;
        }
    }

    //process recv result from server
    while(1){
        recvBytes = recv(g_hSocket, (uint8_t*)&rPack, return_pack_len, 0)

        if(recvBytes == return_pack_len){
            break;
        }else if(recvBytes <=0 && errno != EINTR && errno != EWOULDBLOCK && errno != EAGAIN){
            cout<<"disconnected or error occur!"<<endl;
            return -1;
        }else{
            continue;
        }
    }


    //check header
    if(memcmp(rPack.cmdHeader, tcp_cmd_header, tcp_cmd_header) != 0){
        cout<<"return pack header errror!"<<endl;
        return -2;
    }
    //get return status
    if( rPack.returnCMD != DVS_RETURN_SUCCESS ){
         cout<<"return status : fail!"<<endl;
         return -3;
    }




    return 0;
}